package com.example.lock;


import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;

/***
 *
 * 基于数据库的悲观锁
 */
public class DbLock implements Lock {

    Logger logger = LoggerFactory.getLogger(getClass());

    private DataSource dataSource;

    private Connection connection;

    private boolean autoCommit;

    private String sql;

    private PreparedStatement preparedStatement;

    @Override
    public void lock() throws Exception {
        this.connection = this.dataSource.getConnection();
        this.autoCommit = connection.getAutoCommit();
        this.connection.setAutoCommit(false);
        this.preparedStatement = this.connection.prepareStatement(this.sql);
        this.preparedStatement.execute();
    }

    @Override
    public void unlock() {
        if (this.preparedStatement != null) {
            try {
                this.preparedStatement.close();
            } catch (SQLException e) {
                logger.error(e.getMessage(), e);
            }
        }

        if (this.connection != null) {
            try {
                this.connection.commit();
            } catch (SQLException e) {
                logger.error(e.getMessage(), e);
            }
            try {
                this.connection.setAutoCommit(this.autoCommit);
            } catch (SQLException e) {
                logger.error(e.getMessage(), e);
            }
            try {
                this.connection.close();
            } catch (SQLException e) {
                logger.error(e.getMessage(), e);
            }
        }

    }

    public DbLock(DataSource dataSource, String sql) {
        this.dataSource = dataSource;
        this.sql = sql;
    }

    public DataSource getDataSource() {
        return dataSource;
    }

    public void setDataSource(DataSource dataSource) {
        this.dataSource = dataSource;
    }

    public Connection getConnection() {
        return connection;
    }

    public void setConnection(Connection connection) {
        this.connection = connection;
    }

    public boolean isAutoCommit() {
        return autoCommit;
    }

    public void setAutoCommit(boolean autoCommit) {
        this.autoCommit = autoCommit;
    }

    public PreparedStatement getPreparedStatement() {
        return preparedStatement;
    }

    public void setPreparedStatement(PreparedStatement preparedStatement) {
        this.preparedStatement = preparedStatement;
    }

    public String getSql() {
        return sql;
    }

    public void setSql(String sql) {
        this.sql = sql;
    }
}
